using System;
using System.Runtime.InteropServices;

namespace Leap
{
	public class Controller : Interface
	{
		public enum PolicyFlag
		{
			POLICY_DEFAULT,
			POLICY_BACKGROUND_FRAMES,
			POLICY_IMAGES,
			POLICY_OPTIMIZE_HMD = 4,
			POLICYDEFAULT = 0,
			POLICYBACKGROUNDFRAMES
		}

		private HandleRef swigCPtr;

		public bool IsConnected => LeapPINVOKE.Controller_IsConnected_get(swigCPtr);

		public bool HasFocus => LeapPINVOKE.Controller_HasFocus_get(swigCPtr);

		public PolicyFlag PolicyFlags => (PolicyFlag)LeapPINVOKE.Controller_PolicyFlags_get(swigCPtr);

		public Config Config
		{
			get
			{
				IntPtr intPtr = LeapPINVOKE.Controller_Config_get(swigCPtr);
				return (intPtr == IntPtr.Zero) ? null : new Config(intPtr, true);
			}
		}

		public ImageList Images
		{
			get
			{
				IntPtr intPtr = LeapPINVOKE.Controller_Images_get(swigCPtr);
				return (intPtr == IntPtr.Zero) ? null : new ImageList(intPtr, true);
			}
		}

		public ScreenList LocatedScreens
		{
			get
			{
				IntPtr intPtr = LeapPINVOKE.Controller_LocatedScreens_get(swigCPtr);
				return (intPtr == IntPtr.Zero) ? null : new ScreenList(intPtr, true);
			}
		}

		public DeviceList Devices
		{
			get
			{
				IntPtr intPtr = LeapPINVOKE.Controller_Devices_get(swigCPtr);
				return (intPtr == IntPtr.Zero) ? null : new DeviceList(intPtr, true);
			}
		}

		public TrackedQuad TrackedQuad
		{
			get
			{
				IntPtr intPtr = LeapPINVOKE.Controller_TrackedQuad_get(swigCPtr);
				return (intPtr == IntPtr.Zero) ? null : new TrackedQuad(intPtr, true);
			}
		}

		public BugReport BugReport
		{
			get
			{
				IntPtr intPtr = LeapPINVOKE.Controller_BugReport_get(swigCPtr);
				return (intPtr == IntPtr.Zero) ? null : new BugReport(intPtr, true);
			}
		}

		public Controller(IntPtr cPtr, bool cMemoryOwn)
			: base(LeapPINVOKE.Controller_SWIGUpcast(cPtr), cMemoryOwn)
		{
			swigCPtr = new HandleRef(this, cPtr);
		}

		public static HandleRef getCPtr(Controller obj)
		{
			return obj?.swigCPtr ?? new HandleRef(null, IntPtr.Zero);
		}

		~Controller()
		{
			Dispose();
		}

		public override void Dispose()
		{
			lock (this)
			{
				if (swigCPtr.Handle != IntPtr.Zero)
				{
					if (base.swigCMemOwn)
					{
						base.swigCMemOwn = false;
						LeapPINVOKE.delete_Controller(swigCPtr);
					}
					swigCPtr = new HandleRef(null, IntPtr.Zero);
				}
				GC.SuppressFinalize(this);
				base.Dispose();
			}
		}

		public Controller()
			: this(LeapPINVOKE.new_Controller__SWIG_0(), true)
		{
		}

		public Controller(Listener listener)
			: this(LeapPINVOKE.new_Controller__SWIG_1(Listener.getCPtr(listener)), true)
		{
			if (!LeapPINVOKE.SWIGPendingException.Pending)
			{
				return;
			}
			throw LeapPINVOKE.SWIGPendingException.Retrieve();
		}

		public bool IsServiceConnected()
		{
			return LeapPINVOKE.Controller_IsServiceConnected(swigCPtr);
		}

		public void SetPolicyFlags(PolicyFlag flags)
		{
			LeapPINVOKE.Controller_SetPolicyFlags(swigCPtr, (int)flags);
		}

		public void SetPolicy(PolicyFlag policy)
		{
			LeapPINVOKE.Controller_SetPolicy(swigCPtr, (int)policy);
		}

		public void ClearPolicy(PolicyFlag policy)
		{
			LeapPINVOKE.Controller_ClearPolicy(swigCPtr, (int)policy);
		}

		public bool IsPolicySet(PolicyFlag policy)
		{
			return LeapPINVOKE.Controller_IsPolicySet(swigCPtr, (int)policy);
		}

		public bool AddListener(Listener listener)
		{
			bool result = LeapPINVOKE.Controller_AddListener(swigCPtr, Listener.getCPtr(listener));
			if (LeapPINVOKE.SWIGPendingException.Pending)
			{
				throw LeapPINVOKE.SWIGPendingException.Retrieve();
			}
			return result;
		}

		public bool RemoveListener(Listener listener)
		{
			bool result = LeapPINVOKE.Controller_RemoveListener(swigCPtr, Listener.getCPtr(listener));
			if (LeapPINVOKE.SWIGPendingException.Pending)
			{
				throw LeapPINVOKE.SWIGPendingException.Retrieve();
			}
			return result;
		}

		public Frame Frame(int history)
		{
			return new Frame(LeapPINVOKE.Controller_Frame__SWIG_0(swigCPtr, history), true);
		}

		public Frame Frame()
		{
			return new Frame(LeapPINVOKE.Controller_Frame__SWIG_1(swigCPtr), true);
		}

		public void EnableGesture(Gesture.GestureType type, bool enable)
		{
			LeapPINVOKE.Controller_EnableGesture__SWIG_0(swigCPtr, (int)type, enable);
		}

		public void EnableGesture(Gesture.GestureType type)
		{
			LeapPINVOKE.Controller_EnableGesture__SWIG_1(swigCPtr, (int)type);
		}

		public bool IsGestureEnabled(Gesture.GestureType type)
		{
			return LeapPINVOKE.Controller_IsGestureEnabled(swigCPtr, (int)type);
		}

		public long Now()
		{
			return LeapPINVOKE.Controller_Now(swigCPtr);
		}
	}
}
